package minidb.buffer;
import minidb.file.Page; 


public class Buffer {

	private Page contents;
	private int pageNum;
	private int pins;
	private int modifiedBy;
	private int logSequenceNumber;
	private byte[] lock = new byte[0];
	
	public Buffer(int blk){
		this.pageNum = blk;
		if(pageNum!=0)
			contents = new Page(pageNum);
		this.pins = 0;
		this.modifiedBy = 0;
	}
	
	public void getByte(int position, java.nio.ByteBuffer record, int slot){
		synchronized(lock){
			contents.getByte(position, record, slot);
		}
	}
	
	public void putByte(int position, java.nio.ByteBuffer record, int slot){
		synchronized(lock){
			record.rewind();
			contents.putByte(position, record, slot);
			modifiedBy = 1;
		}
	}
	public int getInt(int offset) {
		synchronized(lock){
			return contents.getInt(offset);
		}
	}
	
	public String getString(int offset) {
		synchronized(lock){
			return contents.getString(offset);
		}
	}
	
	public byte get(int pos){
		synchronized(lock){
			return contents.get(pos);
		}
	}
	public void putInt(int offset, int val) {
		synchronized(lock){
			modifiedBy = 1;
			contents.putInt(offset, val);
		}
	}
	
	public void putString(int offset, String val) {
		synchronized(lock){
			modifiedBy = 1;
			contents.putString(offset, val);
		}
	}
	
	public void put(int pos, byte b){
		synchronized(lock){
			modifiedBy = 1;
			contents.put(pos, b);
		}
	}
	public int pageNum(){
		synchronized(lock){
			return this.pageNum;
		}
	}
	
	public void pageNum(int pageNum){
		synchronized(lock){
			if (modifiedBy > 0) {
				contents.write();
			}
			modifiedBy = 0;
			if(pageNum!=0){
				contents = new Page(pageNum);
				contents.read();
			}
			this.pageNum = pageNum;
		}
	}
	
	public int logSequenceNumber(){
		return logSequenceNumber;
	}
	
	public void flush() {
		synchronized(lock){
			if (modifiedBy > 0) {
				contents.write();
			}
			modifiedBy = 0;
		}
	}
	
	public void pin(){
		/*while(true){
			synchronized(lock){
				if(this.pins<=0){
					this.pins=1;
					break;
				}
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}*/
		this.pins++;
	}
	
	public void unpin(){
		synchronized(lock){
			this.pins--;
			if(this.pins < 0)
				throw new RuntimeException("BUFFER POOL ERROR");
		}
	}
	
	public boolean ispin(){
		synchronized(lock){
			return pins > 0;
		}
	}
	
	public boolean isModifiedBy() {
		synchronized(lock){
			return  modifiedBy == 1;
		}
	}
	
}
